home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Devices and Hardware / CD ROM / CD Tracker / CDTracker.p < prev    next >
Encoding:
Text File  |  2000-09-28  |  11.8 KB  |  413 lines  |  [TEXT/CWIE]

  1. (*
  2.     File:        CDTracker.p
  3.     
  4.     Description:This sample demonstrates how to read the table of contents from an audio
  5.                 CD to work out the number of tracks and the lengths of those tracks.
  6.  
  7.     Author:        
  8.  
  9.     Copyright:     Copyright: © 1984-1999 by Apple Computer, Inc.
  10.                 all rights reserved.
  11.     
  12.     Disclaimer:    You may incorporate this sample code into your applications without
  13.                 restriction, though the sample code has been provided "AS IS" and the
  14.                 responsibility for its operation is 100% yours.  However, what you are
  15.                 not permitted to do is to redistribute the source as "DSC Sample Code"
  16.                 after having made changes. If you're going to re-distribute the source,
  17.                 we require that you make it clear in the source that the code was
  18.                 descended from Apple Sample Code, but that you've made changes.
  19.     
  20.     Change History (most recent first):
  21.                 6/23/99    Updated for Metrowerks Codewarrior Pro 2.1(KG)
  22.  
  23. *)
  24. PROGRAM    CDTracker;
  25. {$R CDTracker.Rsrc}
  26. {$U-}
  27.  
  28. USES
  29.        QuickDraw,
  30.        Types,
  31.        Files,
  32.        Fonts,
  33.        Windows,
  34.        TextEdit,
  35.        Dialogs,
  36.        NumberFormatting,
  37.        Resources,
  38.        Devices,
  39.        StandardFile;
  40.  
  41.  
  42. CONST
  43.     TextStatItem = 2;   {Item number of static text}
  44.     textItem = 3;        {item number for editable text item}
  45. TYPE
  46.     ReadTOCBlk = record
  47.     theBytes : packed array [0..3] of byte;
  48.     end;
  49.     twoBytes = ARRAY [0..1] of signedbyte;
  50.  
  51. VAR
  52.     err : integer;
  53.              DoErrDialPtr,DialPtr,oldPort : DialogPtr;
  54.              DialItemHit, DITLID : integer;
  55.              DITLHndl : handle;
  56.     CloseWind :boolean;
  57.     x,y : integer;        {scratch ints}
  58.     theType : integer;   {gives the type of the item requested}
  59.     theTextHdl : handle;    {gives a handle to the item}
  60.     txtBox : Rect;    {gives the display rectangle of the item}
  61.     DrvrRefNum : integer;
  62.     {MyFFSynthPtr : FFSynthPtr;}
  63.     StartTrk,EndTrak,BCDTrackNo : signedbyte;
  64.     NumTracks, TrkIndex : integer;
  65.     EndOfDiskBlk : ReadTOCBlk;
  66.  
  67.  
  68.  
  69.         {------------------------------------------------------------------------------------}
  70.     
  71.   {PROCEDURE debugger; INLINE $A9FF;}
  72.  
  73.         {------------------------------------------------------------------------------------}
  74.  
  75.         PROCEDURE InitMac;
  76.  
  77.             BEGIN                       {InitMac}
  78.  
  79.    InitGraf (@qd.thePort);          {the big five inits}
  80.    InitFonts;
  81.    InitWindows;
  82.    TEInit;
  83.    InitDialogs (nil);
  84.  
  85.             END;                       {InitMac}
  86.  
  87.         {------------------------------------------------------------------------------------}
  88.  
  89. FUNCTION BCDtoHex (SrcByte:signedbyte):integer;
  90.  
  91. VAR
  92.     x,y : integer;
  93.  
  94. begin
  95.     x := integer(SrcByte MOD 16);
  96.     y := integer(SrcByte DIV 16);
  97.     y := y*10;
  98.     BCDtoHex := x+y;
  99. end;
  100.  
  101.         {------------------------------------------------------------------------------------}
  102.  
  103. FUNCTION HextoBCD (SrcInt:integer):signedbyte;
  104.  
  105. VAR
  106.     x,y : integer;
  107.     z : signedbyte;
  108.  
  109. begin
  110.     z := $0;
  111.     x := SrcInt MOD 256;
  112.     y := x;
  113.     if y >= 10 then
  114.     begin
  115.         z := z + $10;
  116.         repeat
  117.             y := y-10;
  118.             if y > 10 then z := z + $10;
  119.         until (y < 10);
  120.     end;
  121.     HextoBCD := signedbyte(y)+z;
  122. end;
  123.  
  124.         {------------------------------------------------------------------------------------}
  125.  
  126. PROCEDURE DoError (ErStr : str255; err : longint);
  127.  
  128. VAR
  129.     NumStr : str255;
  130.  
  131.     Begin
  132.         GetPort (oldPort);
  133.         if err <> noerr then
  134.         begin
  135.         NumToString (err,NumStr);
  136.         ErStr := Concat (ErStr,NumStr);
  137.         end;
  138.         DITLID := 257;
  139.         DITLHndl := GetResource ('DITL', DITLID);
  140.         err := ResError;
  141.         if err = noerr then
  142.         begin
  143.         if DITLHndl <> nil then
  144.  
  145.         begin
  146.             Hlock (DITLHndl);
  147.             DoErrDialPtr := GetNewDialog (257,nil,WindowPtr(-1));
  148.             If DoErrDialPtr <> nil then
  149.             begin
  150.             GetDialogItem (DoErrDialPtr, TextStatItem, theType, theTextHdl, txtBox);
  151.             If theTextHdl <> nil then
  152.             begin
  153.      
  154.             SetPort (DoErrDialPtr);
  155.  
  156.             SetDialogItemText (theTextHdl, ErStr);
  157.             repeat
  158.             ModalDialog (nil, DialItemHit);
  159.             until DialItemHit <> 0;
  160.             Case DialItemHit of  {1 = OK btn, 2 = message}
  161.                 1,2 : CloseDialog (DoErrDialPtr);
  162.                                 
  163.                         end; {case}
  164.             end;
  165.             end;
  166.         end;
  167.         end;
  168.         setPort (oldPort);
  169.      end;
  170.  
  171.         {------------------------------------------------------------------------------------}
  172.  
  173. PROCEDURE GetTrackInfo (dRefNum,trackNo:integer);
  174.  
  175. TYPE
  176.     longintptr = ^ptr;
  177.     bytePtr = ^signedbyte;
  178. VAR
  179.     PB : ParamBlockRec;
  180.     theStr : str255;
  181.     aByte : signedbyte;
  182.     x,y,z : integer;
  183.     DataPtr : longintptr;
  184.     DataBlock : ReadTOCBlk;
  185.     BytePoint : bytePtr;
  186.     carry : boolean;
  187.  
  188. begin
  189. carry := false;
  190.     BCDTrackNo := HexToBCD (trackNo);
  191.     PB.ioCompletion := nil;
  192.     PB.ioRefNum := dRefNum;
  193.     PB.csCode := 100;
  194.     PB.csParam[0] := 3;
  195.     DataPtr := @PB.csParam[1];
  196.     DataPtr^ := @DataBlock;
  197.     PB.csParam[3] := 4;
  198.     bytePoint := @PB.csParam[4];
  199.     bytePoint^ := signedbyte(BCDTrackNo);
  200.     err := PBControl (@PB,false);
  201.     if err = noerr then
  202.     begin
  203.         if trackNo = NumTracks then
  204.         Begin
  205.             BytePoint := @PB.csParam[1];
  206.             BytePoint := bytePtr(longint(BytePoint)+1);
  207.             BytePoint^ := EndOfDiskBlk.theBytes[0];
  208.             BytePoint := bytePtr(longint(BytePoint)+1);
  209.             BytePoint^ := EndOfDiskBlk.theBytes[1];
  210.             BytePoint := bytePtr(longint(BytePoint)+1);
  211.             BytePoint^ := EndOfDiskBlk.theBytes[2];
  212.             BytePoint := bytePtr(longint(BytePoint)+1);
  213.         end
  214.         else
  215.         begin
  216.             PB.ioCompletion := nil;
  217.             PB.ioRefNum := dRefNum;
  218.             PB.csCode := 103;
  219.             PB.csParam[0] := 2;
  220.             PB.csParam[1] := 0;
  221.             z := BCDToHex (BCDTrackNo);
  222.             z := z+1;
  223.             aByte := HexToBCD (z);
  224.             PB.csParam[2] := aByte;
  225.             PB.csParam[3] := 0;
  226.             err := PBControl (@PB,false);
  227.             if err = noerr then
  228.                 begin
  229.                     PB.ioCompletion := nil;
  230.                     PB.ioRefNum := dRefNum;
  231.                     PB.csCode := 107;
  232.                     err := PBControl (@PB,false);
  233.                 end
  234.                 else doError ('PBControl (103) error = ',err);
  235.         end;
  236.         if err = noerr then
  237.         begin
  238.             NumToString(longint(trackNo),theStr);
  239.             GetDialogItem (DialPtr, 6, theType, theTextHdl, txtBox);
  240.             If theTextHdl <> nil then SetDialogItemText (theTextHdl,theStr);
  241.                 
  242.             aByte := DataBlock.theBytes[3];  {do frames first}
  243.             x := BCDtoHex (aByte);
  244.             aByte := signedbyte(twoBytes(PB.csParam[2])[1]);
  245.             y := BCDtoHex (aByte);
  246.             z := y-x;
  247.             if (z < 0) then
  248.             begin
  249.                 z := z + 74;   {74 frames/sec}
  250.                 carry := true;
  251.             end
  252.             else carry := false;
  253.             NumToString(z,theStr);
  254.             GetDialogItem (DialPtr, 9, theType, theTextHdl, txtBox);
  255.             If theTextHdl <> nil then SetDialogItemText (theTextHdl,theStr);
  256.                 
  257.             aByte := DataBlock.theBytes[2];  {do seconds second}
  258.             x := BCDtoHex (aByte);
  259.             aByte := signedbyte(twoBytes(PB.csParam[2])[0]);
  260.             y := BCDtoHex (aByte);
  261.             if carry then y := y-1;
  262.             z := y-x;
  263.             if (z < 0) then
  264.             begin
  265.                 z := z + 60;    {60 seconds/minute}
  266.                 carry := true;
  267.             end
  268.             else carry := false;
  269.             NumToString(z,theStr);
  270.             GetDialogItem (DialPtr, 8, theType, theTextHdl, txtBox);
  271.             If theTextHdl <> nil then SetDialogItemText (theTextHdl,theStr);
  272.                 
  273.             aByte := DataBlock.theBytes[1];
  274.             x := BCDtoHex (aByte);
  275.             aByte := signedbyte(twoBytes(PB.csParam[1])[1]);
  276.             y := BCDtoHex (aByte);
  277.             if carry then y := y-1;
  278.             z := y-x;
  279.             NumToString(z,theStr);
  280.             GetDialogItem (DialPtr, 7, theType, theTextHdl, txtBox);
  281.             If theTextHdl <> nil then SetDialogItemText (theTextHdl,theStr);
  282.         end
  283.         else doError ('PBControl (107) error = ',err);
  284.     end
  285.     else doError ('PBControl (100,3) error = ',err);
  286. end;
  287.                 
  288.         {------------------------------------------------------------------------------------}
  289.  
  290. PROCEDURE GetCDInfo(dRefNum:integer;VAR StrtTrk,EndTrk:signedbyte);
  291.     
  292. VAR
  293.     PB : ParamBlockRec;
  294.  
  295. begin
  296.     PB.ioCompletion := nil;
  297.     PB.ioRefNum := dRefNum;
  298.     PB.csCode := 100;
  299.     PB.csParam[0] := 1;
  300.     err := PBControl (@PB,false);
  301.     if err = noerr then
  302.     begin
  303.         StrtTrk := signedbyte(twoBytes(PB.csParam[0])[0]);
  304.         EndTrk := signedbyte(twoBytes(PB.csParam[0])[1]);
  305.     end
  306.     else doError ('PBControl (100,1) error = ',err);
  307. end;
  308.  
  309.         {------------------------------------------------------------------------------------}
  310.  
  311. PROCEDURE GetEndOfDisk (dRefNum:integer;VAR datablk:ReadTOCBlk);
  312.  
  313. VAR
  314.     PB : ParamBlockRec;
  315.  
  316. begin
  317.     PB.ioCompletion := nil;
  318.     PB.ioRefNum := dRefNum;
  319.     PB.csCode := 100;
  320.     PB.csParam[0] := 2;
  321.     err := PBControl (@PB,false);
  322.     if err = noerr then
  323.     begin
  324.         datablk.theBytes[0] := signedbyte(twoBytes(PB.csParam[0])[0]);
  325.         datablk.theBytes[1] := signedbyte(twoBytes(PB.csParam[0])[1]);
  326.         datablk.theBytes[2] := signedbyte(twoBytes(PB.csParam[1])[0]);
  327.         datablk.theBytes[3] := signedbyte(twoBytes(PB.csParam[1])[1]);
  328.     end
  329.     else doError ('PBControl (100,1) error = ',err);
  330. end;
  331.  
  332.     
  333.  
  334.         {------------------------------------------------------------------------------------}
  335.  
  336. FUNCTION GetDrvr:Integer;
  337.  
  338. VAR
  339.     MyReply : SFReply;
  340.     Place : point;
  341.     MyTypeList : SFTypeList;
  342.     PB : HParamBlockRec;
  343.     
  344. Begin
  345.     
  346.     Place.v := 50;
  347.     Place.h := 50;
  348.     SFGetFile (Place,"",nil,-1,@MyTypeList,nil,MyReply);
  349.     if MyReply.good then
  350.     begin
  351.         PB.ioCompletion := nil;
  352.         PB.ioNamePtr := nil;
  353.         PB.ioVRefNum := MyReply.vRefNum;
  354.         PB.ioVolIndex := 0;
  355.         err := PBHGetVInfoSync(@PB);
  356.         if err = noerr then GetDrvr := PB.ioVDRefNum
  357.         else GetDrvr := 0;
  358.     end
  359.     else GetDrvr := 0;
  360. end;
  361.  
  362.         {------------------------------------------------------------------------------------}
  363.  
  364. begin
  365.     initmac;
  366.     DITLID := 256;
  367.     DITLHndl := GetResource ('DITL', DITLID);
  368.     err := ResError;
  369.     if err = noerr then
  370.     begin
  371.         if DITLHndl <> nil then
  372.                     begin
  373.             Hlock (DITLHndl);                    
  374.             DialPtr := GetNewDialog (256,nil,WindowPtr(-1));
  375.             SetPort (DialPtr);
  376.             If DialPtr <> nil then
  377.             begin
  378.                 DrvrRefNum := GetDrvr;
  379.                 GetCDInfo (DrvrRefNum,StartTrk,EndTrak);
  380.                 x := BCDtoHex (EndTrak);
  381.                 y := BCDtoHex (StartTrk);
  382.                 NumTracks := x-y+1;
  383.                 GetTrackInfo (DrvrRefNum,1);
  384.                 TrkIndex := 1;
  385.                 GetEndOfDisk (DrvrRefNum,EndOfDiskBlk);
  386.                 CloseWind := False;
  387.                 repeat
  388.                 begin
  389.                     repeat
  390.                     ModalDialog (nil, DialItemHit);
  391.                     until DialItemHit <> 0;
  392.                     Case DialItemHit of  {1 = OK btn, 10 = message, 3 = edittext}
  393.                     1 : begin
  394.                             CloseDialog (DialPtr);
  395.                             CloseWind := True;
  396.                         end;
  397.                     10 : begin
  398.                             TrkIndex := TrkIndex + 1;
  399.                             if TrkIndex > NumTracks then TrkIndex := 1;
  400.                             GetTrackInfo (DrvrRefNum,TrkIndex);
  401.                             If err <> noerr then trkIndex := trkIndex-1;
  402.                         end;
  403.                     end; {case}
  404.                 end;
  405.                 until closewind;
  406.             end 
  407.             else DoError ('DialPtr Nil',0);
  408.             HUnlock (DITLHndl);
  409.         end
  410.         else DoError ('DITL Handle Nil',0);
  411.     end
  412.     else DoError ('Resource Error = ',err);
  413. end.